#ifndef PROCESS_POOL_HPP
#define PROCESS_POOL_HPP

#include <iostream>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
#include <unistd.h>
#include "Task.hpp"

#define pipenum 5


class Channel
{
public:
    Channel(int wfd, pid_t pid):_wfd(wfd), _pid(pid) {
        _name = "Channel " + std::to_string(wfd) + " " + std::to_string(pid);
    }

    int GetWfd() const { return _wfd; }
    pid_t GetPid() const { return _pid; }
    std::string GetName() const { return _name; }

    //将任务代号发给子进程
    int Send(int code){
        ssize_t n = write(_wfd, &code, sizeof(code));
        (void)n;
    }

    void Close(){
        close(_wfd);
    }

    void Wait(){
        pid_t rid = waitpid(_pid, nullptr, 0);
        (void)rid;
    }

    ~Channel() {}

private:
    int _wfd;
    pid_t _pid;
    std::string _name;
};

class ChannelManager
{
public:
    ChannelManager() {
        _next = 0;
    }

    void Insert(int wfd, pid_t pid){
        Channel newchannel(wfd, pid);
        _channels.push_back(newchannel);
    }

    Channel& Select(){
        Channel& c = _channels[_next];
        _next++;
        _next %= _channels.size();
        return c;
    }

    void StopSubProcess(){
        for(auto &channal : _channels){
            channal.Close();
            std::cout<<"关闭子进程"<<channal.GetPid()<<std::endl;
        }
    }

    void WaitSubProcess(){
        for(auto &channal : _channels){
            channal.Wait();
            std::cout<<"进程回收"<<std::endl;
        }
    }

    void Closeall(){
        for(auto &channal : _channels){
            channal.Close();
        }
    }

    void Show(){
        std::cout<<"当前管道数量："<<_channels.size()<<std::endl;
        for(auto &channal : _channels){
            std::cout<<channal.GetName()<<std::endl;
            sleep(5);
        }
    }

    ~ChannelManager() {}

private:
    std::vector<Channel> _channels;
    int _next;
};

class ProcessPool
{
public:
    ProcessPool() :_pipenum(pipenum){
        _tm.Register(PrintLog);
        _tm.Register(Download);
        _tm.Register(Upload);
    }

    void Work(int fd){
        // std::cout<<"我是子进程，我开始工作了!我的fd是: "<<fd<<" "<<std::endl;
        // sleep(3);

        int code = 0;
        while(true){
            ssize_t n = read(fd, &code, sizeof(code));
            if(n > 0){
                if(n != sizeof(code))
                    continue;

                
                std::cout<<"子进程"<<getpid()<<"获取的任务号是：["<<code<<"] "<<std::endl;
                _tm.Execute(code);
            }
            else if(n == 0){
                std::cout<<"结束读取，子进程退出"<<std::endl;
                break;
            }
            else{
                std::cout<<"读取错误"<<std::endl;
                break;
            }
        }
    }

    void Run(){

        //1、选择一个任务
        int code = _tm.Code();
        std::cout<<"选择的任务号为:"<<code<<std::endl;
        
        //2、选择一个信道
        Channel& c = _cm.Select();

        //3、发送任务
        c.Send(code);
    }

    void Stop(){
        _cm.StopSubProcess();
        _cm.WaitSubProcess();
    }



    void Create(){
        //循环创建管道
        for(int i=0;i<_pipenum;i++){
            //创建管道+验证
            int pipefd[2] = {0};
            int ppfd = pipe(pipefd);
            if(ppfd < 0){
                std::cerr<<"pipe error"<<std::endl;
            }

            //创建子进程+验证
            pid_t pid = fork();
            if(pid < 0){
                std::cerr<<"fork error"<<std::endl;
            }
            else if(pid == 0){
                //子进程

                //提前把之前的写端关闭
                _cm.Closeall();
                close(pipefd[1]); //关闭写端
                Work(pipefd[0]);
                close(pipefd[0]);
                exit(0);
            }
            else{
                //父进程
                close(pipefd[0]);//关闭读端
                _cm.Insert(pipefd[1], pid);
            }
        }

    }

    void Debug(){
        _cm.Show();
    }

    ~ProcessPool(){}

private:
    ChannelManager _cm;
    int _pipenum;
    TaskManager _tm;
};

#endif